package TXPathFinder;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Hashtable;
import org.xml.sax.InputSource;

/**
*       \class	PathFindingWrapper
*	\brief	Gère la communication avec le programme C++
**/
public class PathFindingWrapper
{
    SocketClient _client = null;
    ExternProcess _pathFindingApp = new ExternProcess(new String[] {"..\\PF\\Release\\PF.exe"},false);
    XMLParser _parser = new XMLParser();

    /**
    *	\brief	Constructeur
    **/
    public PathFindingWrapper()
    {
        // On lance l'application C++
        _pathFindingApp.start();
        _client = new SocketClient("localhost");
    }

    /**
    *	\brief	Apelle au programme C++
    *   \param function Fonction apellée
    **/
    protected InputSource call(String function)
    {
        _client.write(function);
        String str = _client.read();
        return new InputSource(new StringReader(str));
    }

    /**
    *	\brief	Fonction C++ : pour demander la map
    *   \return La map à afficher en 3D dans le viewer
    **/
    public Map3D getMap()
    {
        return _parser.getMap(call("<GetMap/>"));
    }

    /**
    *	\brief	Fonction C++ : pour charger une map via une fichier texte
    *   \param Le nom du fichier de la map à charger
    **/
    void loadMap(String mapPath)
    {
        call("<LoadMap Path=\"" + mapPath + "\" />");
    }

    /**
    *	\brief	Fonction C++ : demander la liste des avatars présents
    *   \return La liste des avatars
    **/
    public Hashtable<Integer, Coordonnee> getAgents()
    {
        return _parser.getAgents(call("<GetAgents/>"));
    }

    /**
    *	\brief	Fonction C++ : demander la map cognitive
    *   \param agentId L'identifiant de l'avatar
    *   \return La map cognitive pour un id spécifié
    **/
    public CognitionMap GetCognitionMap(int agentId)
    {
         return _parser.getCognitionMap(call("<GetCognitionMap Id=\"" + agentId + "\" />"));
    }

    /**
    *	\brief	Fonction C++  : demande d'ajout d'un agent aléatoirement
    *   \return Les coordonnées de l'agent ajouté
    **/
    public Coordonnee addAgent()
    {
        return _parser.getAgent(call("<AddAgent/>"));
    }

    /**
    *	\brief	Fonction C++ : demande d'ajout d'un agent au coordonnées spécifiées en parametre
    *   \param row La ligne ou on veut ajouter l'agent
    *   \param col La colonne ou on veut ajouter l'agent
    *   \return Les coordonnées de l'agent ajouté (différente si un agent été déjà présent à la position spécifiée)
    **/
    public Coordonnee addAgent(int row, int col)
    {
        return _parser.getAgent(call("<AddAgent Row=\"" + row + "\" Col=\"" + col + "\" />"));
    }

    /**
    *	\brief	Fonction C++  : Donne la destination générale des avatars au C++
    *   \param row La ligne de destination de l'avatar
    *   \param col La colonne de destination de l'avatar
    **/
    public void goTo(int row, int col)
    {
        call("<GoTo Row=\"" + row + "\" Col=\"" + col + "\" />");
    }

    /**
    *	\brief	Fonction C++  : Donne la destination de l'avatar spécifié
    *   \param agentId Id de l'avatar
    *   \param row La ligne de destination de l'avatar
    *   \param col La colonne de destination de l'avatar
    **/
    public void goTo(int agentId, int row, int col)
    {
        call("<GoTo Id=\"" + agentId + "\" Row=\"" + row + "\" Col=\"" + col + "\" />");
    }

    /**
    *	\brief	Fonction C++  : demander de lancer le déplacement des avatars
    **/
    public void run()
    {
        call("<Run/>");
    }

    /**
    *	\brief	Fonction C++  : demander de stoper le déplacement des avatars
    **/
    void stop()
    {
        call("<Stop/>");
    }

    /**
    *	\brief	Fonction C++  : Quitter le programme 
    **/
    public void exit()
    {
        call("<Exit/>");
    }

    /**
    *	\brief	Fonction C++  : demander de lancer le déplacement d'une foule d'avatar
    **/
    public void startCrowd()
    {
        call("<StartCrowd/>");
    }

    /**
    *	\brief	Fonction C++  : demander d'arreter le deplacement d'une foule d'avatar
    **/
    public void stopCrowd()
    {
        call("<StopCrowd/>");
    }
}
